template<class T>
struct DFDef
{
	void operator()(T*& ptr)
	{
		if (ptr)
		{
			delete ptr;
			ptr = nullptr;
		}
	}
};


template<class T>
struct Free
{
	void operator()(T*& ptr)
	{
		if (ptr)
		{
			free(ptr);
			ptr = nullptr;
		}
	}
};

struct FClose
{
	void operator()(FILE* pf)
	{
		if (pf)
		{
			fclose(pf);
			pf = nullptr;
		}
	}
};

template<class T>
struct DeArr
{
	void operator()(T*& ptr)
	{
		if (ptr)
		{
			delete[] ptr;
			ptr = nullptr;
		}
	}
};
namespace dun
{
	template<class T, class DF = DFDef<T>>
	class unique_ptr
	{
	public:
		// RAII
		unique_ptr(T* ptr = nullptr)
			: _ptr(ptr)
		{}

		~unique_ptr()
		{
			if (_ptr)
			{
				// delete _ptr;
				DF df;   // 仿函数
				df(_ptr);
				_ptr = nullptr;
			}
		}

		// 具有指针类似的行为
		T& operator*()
		{
			return*_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

		// 解决浅拷贝方式：防拷贝--不允许拷贝：不允许调用拷贝构造 以及 赋值运算符重载
		// C++11
		// 在默认成员函数之后跟上=delete：显式告诉编译器该成员函数不用生成了
		unique_ptr(const unique_ptr<T>&) = delete;
		unique_ptr<T>& operator=(const unique_ptr<T>&) = delete;

		T* Get()
		{
			return _ptr;
		}

	private:
		T* _ptr;
	};
}


void TestUniquePtr()
{
	dun::unique_ptr<int> up1(new int);

	dun::unique_ptr<int, Free<int>> up2((int*)malloc(sizeof(int)));

	dun::unique_ptr<FILE, FClose> up3(fopen("111.txt", "w"));

	// 注意：对于连续的空间一般不会较高unique_ptr(智能指针)来管理
	// 因为：STL中已经提供了vector
	dun::unique_ptr<int, DeArr<int>> up4(new int[10]);
}
